#include "imagescaler.h"

ImageScaler::ImageScaler(void) {
#ifdef  Debug_Falg
qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    // 将缩放上下文指针初始化为NULL，表示当前没有有效的缩放上下文
    sws_ctx_ = NULL;
    // 将源图像像素格式初始化为AV_PIX_FMT_NONE，表示无有效像素格式
    src_pix_fmt_ = AV_PIX_FMT_NONE;
    // 将目标图像像素格式初始化为AV_PIX_FMT_NONE，表示无有效像素格式
    dst_pix_fmt_ = AV_PIX_FMT_NONE;
    // 将缩放算法初始化为SWS_SA_FAST_BILINEAR，即快速双线性插值算法
    en_alogrithm_ = SWS_FAST_BILINEAR;

    // 将源图像的宽度和高度初始化为0
    src_width_ = src_height_ = 0;
    // 将目标图像的宽度和高度初始化为0
    dst_width_ = dst_height_ = 0;
}

ImageScaler::~ImageScaler(void) {
    DeInit();
}


RET_CODE ImageScaler::Init(uint32_t src_width, uint32_t src_height, int src_pix_fmt,
              uint32_t dst_width, uint32_t dst_height, int dst_pix_fmt,
              int en_alogrithm) {
#ifdef  Debug_Falg
qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    // 设置源图像的宽度
    src_width_ = src_width;
    // 设置源图像的高度
    src_height_ = src_height;
    // 将传入的源图像像素格式转换为 AVPixelFormat 类型并赋值
    src_pix_fmt_ = (AVPixelFormat)src_pix_fmt;
    // 设置目标图像的宽度
    dst_width_ = dst_width;
    // 设置目标图像的高度
    dst_height_ = dst_height;
    // 将传入的目标图像像素格式转换为 AVPixelFormat 类型并赋值
    dst_pix_fmt_ = (AVPixelFormat)dst_pix_fmt;
    // 设置图像缩放算法
    en_alogrithm_ = en_alogrithm;
    // 创建一个 SwsContext 对象，用于图像缩放操作
    sws_ctx_ = sws_getContext(
                src_width_,  // 源图像宽度
                src_height_, // 源图像高度
                (AVPixelFormat)src_pix_fmt_, // 源图像像素格式
                dst_width_,  // 目标图像宽度
                dst_height_, // 目标图像高度
                (AVPixelFormat)dst_pix_fmt_, // 目标图像像素格式
                // 此处硬编码为 SWS_FAST_BILINEAR，建议使用传入的 en_alogrithm 参数
                SWS_FAST_BILINEAR, 
                NULL,  // 源图像滤波器
                NULL,  // 目标图像滤波器
                NULL   // 缩放算法参数
                );
    // 检查 SwsContext 对象是否创建成功
    if (!sws_ctx_) {
        // 创建失败，返回错误码
        return RET_FAIL;
    }
    return RET_OK;
}

void ImageScaler::DeInit( ) {
#ifdef  Debug_Falg
qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(sws_ctx_) {
        sws_freeContext(sws_ctx_);
        sws_ctx_ = NULL;
    }
}


RET_CODE ImageScaler::Scale(const AVFrame *src_frame, AVFrame *dst_frame) {
#ifdef  Debug_Falg
qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(src_frame->width != src_width_
            || src_frame->height != src_height_
            || src_frame->format != src_pix_fmt_
            || dst_frame->width != dst_width_
            || dst_frame->height != dst_height_
            || dst_frame->format != dst_pix_fmt_
            || !sws_ctx_) {
        // 重新初始化
        DeInit();
        RET_CODE ret = Init(src_frame->width, src_frame->height, src_frame->format,
                            dst_frame->width, dst_frame->height, dst_frame->format,
                            en_alogrithm_);
        if(ret != RET_OK) {
            return ret;
        }
    }

    int dst_slice_h = sws_scale(sws_ctx_, (const uint8_t **) src_frame->data, src_frame->linesize, 0, src_frame->height,
                                dst_frame->data, dst_frame->linesize);
    if(dst_slice_h>0)
        return RET_OK;
    else
        return RET_FAIL;
}

RET_CODE ImageScaler::Scale2(const VideoFrame *src_frame, VideoFrame *dst_frame) {
#ifdef  Debug_Falg
qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(src_frame->width != src_width_
            || src_frame->height != src_height_
            || src_frame->format != src_pix_fmt_
            || dst_frame->width != dst_width_
            || dst_frame->height != dst_height_
            || dst_frame->format != dst_pix_fmt_
            || !sws_ctx_) {
        DeInit();
        RET_CODE ret = Init(src_frame->width, src_frame->height, src_frame->format,
                            dst_frame->width, dst_frame->height, dst_frame->format,
                            en_alogrithm_);
        if(ret != RET_OK) {
            return ret;
        }
    }
    int dst_slice_h = sws_scale(sws_ctx_,
                                (const uint8_t **)src_frame->data,
                                src_frame->linesize,
                                0,  // 起始位置
                                src_frame->height, //处理多少行
                                dst_frame->data,
                                dst_frame->linesize);
    if(dst_slice_h>0)
        return RET_OK;
    else
        return RET_FAIL;
}
RET_CODE ImageScaler::Scale3(const Frame *src_frame, VideoFrame *dst_frame) {
//#ifdef  Debug_Falg//循环
//    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
//#endif

    // 检查源帧和目标帧的参数是否与当前缩放上下文匹配，若不匹配或缩放上下文无效则需要重新初始化
    if(src_frame->width != src_width_
            || src_frame->height != src_height_
            || src_frame->format != src_pix_fmt_
            || dst_frame->width != dst_width_
            || dst_frame->height != dst_height_
            || dst_frame->format != dst_pix_fmt_
            || !sws_ctx_) {
        // 释放当前的缩放上下文
        DeInit();

        // 重新初始化缩放上下文，使用源帧和目标帧的实际参数
        RET_CODE ret = Init(src_frame->width, 
                            src_frame->height, 
                            src_frame->format,
                            dst_frame->width, 
                            dst_frame->height, 
                            dst_frame->format,
                            en_alogrithm_);
        if(ret != RET_OK) {
            return ret;
        }
    }

    // 调用 FFmpeg 的 sws_scale 函数进行图像缩放操作
    int dst_slice_h = sws_scale(sws_ctx_,// 缩放上下文
                                (const uint8_t **)src_frame->frame->data,// 源帧的数据指针数组
                                src_frame->frame->linesize,// 源帧每行数据的字节数数组
                                0,  // 起始位置
                                src_frame->height, //处理多少行
                                dst_frame->data,// 目标帧的数据指针数组
                                dst_frame->linesize);// 目标帧每行数据的字节数数组
    if(dst_slice_h>0)
        return RET_OK;
    else
        return RET_FAIL;
}
